{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Running Commands on Amazon Bedrock AgentCore Code Interpreter - Tutorial\n",
    "\n",
    "This tutorial demonstrates how to use Amazon Bedrock AgentCore Code Interpreter to run commands (shell and AWS CLI). We will interact with AWS services, specifically focusing on S3 operations. We'll walk through:\n",
    "\n",
    "1. Creating a code interpreter\n",
    "2. Start code interpreter session\n",
    "3. Run Commands(shell and AWS CLI)\n",
    "5. Performing S3 operations(create bucket, copy objects, list bucket objects)\n",
    "6. Cleanup (stop session and delete code interpreter)\n",
    "\n",
    "\n",
    "\n",
    "## Prerequisites\n",
    "- AWS account with Bedrock AgentCore Code Interpreter access\n",
    "- You have the necessary IAM permissions to create and manage code interpreter resources\n",
    "- YOu have the necessary IAM permissions to perform s3 operations\n",
    "- Required Python packages installed(including boto3 & bedrock-agentcore)\n",
    "\n",
    "\n",
    "## Your IAM execution role should have the following IAM policy attached"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "~~~ {\n",
    "    \"Version\": \"2012-10-17\",\n",
    "    \"Statement\": [\n",
    "        {\n",
    "            \"Effect\": \"Allow\",\n",
    "            \"Action\": [\n",
    "                \"bedrock-agentcore:CreateCodeInterpreter\",\n",
    "                \"bedrock-agentcore:StartCodeInterpreterSession\",\n",
    "                \"bedrock-agentcore:InvokeCodeInterpreter\",\n",
    "                \"bedrock-agentcore:StopCodeInterpreterSession\",\n",
    "                \"bedrock-agentcore:DeleteCodeInterpreter\",\n",
    "                \"bedrock-agentcore:ListCodeInterpreters\",\n",
    "                \"bedrock-agentcore:GetCodeInterpreter\"\n",
    "            ],\n",
    "            \"Resource\": \"*\"\n",
    "        },\n",
    "        {\n",
    "            \"Effect\": \"Allow\",\n",
    "            \"Action\": [\n",
    "                \"logs:CreateLogGroup\",\n",
    "                \"logs:CreateLogStream\",\n",
    "                \"logs:PutLogEvents\"\n",
    "            ],\n",
    "            \"Resource\": \"arn:aws:logs:*:*:log-group:/aws/bedrock-agentcore/code-interpreter*\"\n",
    "        }\n",
    "    ]\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### The IAM execution role should also have the following trust policy attached. By including bedrock-agentcore.amazonaws.com in the trust policy, you're allowing the Bedrock Agent service itself to assume this IAM role and perform actions on your behalf(such as Amazon S3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```{\n",
    "    \"Version\": \"2012-10-17\",\n",
    "    \"Statement\": [\n",
    "        {\n",
    "            \"Effect\": \"Allow\",\n",
    "            \"Principal\": {\n",
    "                \"AWS\": \"arn:aws:iam::558228106740:root\",\n",
    "                \"Service\": [\n",
    "                    \"bedrock-agentcore.amazonaws.com\"\n",
    "                ]\n",
    "            },\n",
    "            \"Action\": \"sts:AssumeRole\",\n",
    "            \"Condition\": {}\n",
    "        }\n",
    "    ]\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Additionally, you need to attach the AmazonS3FullAccess IAM policy to the IAM Execution role to perform the s3 operations described in this tutorial"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## How it works\n",
    "\n",
    "The code execution sandbox enables agents to safely process user queries by creating an isolated environment with a code interpreter, shell, and file system. After a Large Language Model helps with tool selection, code is executed within this session, before being returned to the user or Agent for synthesis.\n",
    "\n",
    "![architecture local](code-interpreter.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Setting Up the Environment\n",
    "\n",
    "First, let's import the necessary libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install --upgrade -r requirements.txt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:38:33.000173Z",
     "start_time": "2025-07-13T12:38:32.995251Z"
    }
   },
   "outputs": [],
   "source": [
    "import json\n",
    "import boto3\n",
    "from bedrock_agentcore.tools.code_interpreter_client import code_session, CodeInterpreter\n",
    "from bedrock_agentcore._utils import endpoints\n",
    "import time\n",
    "from typing import Dict, Any, List"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Configuration Variables\n",
    "\n",
    "Set up the necessary configuration variables for code interpreter and S3 operations. We also provide an IAM execution role to pass to the code interpreter,so that it can assume it to access other AWS resources. This role needs S3 permissions, as discussed above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:56:35.843558Z",
     "start_time": "2025-07-13T12:56:35.834789Z"
    }
   },
   "outputs": [],
   "source": [
    "# Configuration setup\n",
    "execution_role_arn = \"<execution-role-arn>\"\n",
    "unique_bucket_name = f\"amzn-bucket-{int(time.time())}\"\n",
    "s3_path = f\"s3://{unique_bucket_name}\"\n",
    "\n",
    "region = \"us-west-2\"\n",
    "\n",
    "#local file that we will upload to Code interpreter and then to an S3 bucket\n",
    "local_file = \"samples/stats.py\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Setting up endpoints\n",
    "\n",
    "We need to configure both data plane and control plane endpoints to create the boto3 clients."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:56:39.350883Z",
     "start_time": "2025-07-13T12:56:39.346623Z"
    }
   },
   "outputs": [],
   "source": [
    "# Configure endpoints\n",
    "data_plane_endpoint = endpoints.get_data_plane_endpoint(region)\n",
    "control_plane_endpoint = endpoints.get_control_plane_endpoint(region)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Creating AWS Clients\n",
    "\n",
    "Initialize boto3 clients for both control plane and data plane operations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:56:43.741864Z",
     "start_time": "2025-07-13T12:56:43.720200Z"
    }
   },
   "outputs": [],
   "source": [
    "# Create boto3 clients\n",
    "cp_client = boto3.client(\"bedrock-agentcore-control\", \n",
    "                        region_name=region,\n",
    "                        endpoint_url=control_plane_endpoint)\n",
    "\n",
    "dp_client = boto3.client(\"bedrock-agentcore\", \n",
    "                        region_name=region,\n",
    "                        endpoint_url=data_plane_endpoint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Creating a Code Interpreter\n",
    "\n",
    "Create a code interpreter instance with specific configuration parameters.\n",
    "\n",
    "When configuring a code interpreter, you can choose network settings (Sandbox, Public, or VPC), dependencies configuration, security settings, and permissions through an IAM runtime role that defines what AWS resources the code interpreter can access."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:56:51.810308Z",
     "start_time": "2025-07-13T12:56:50.250747Z"
    }
   },
   "outputs": [],
   "source": [
    "# Create code interpreter\n",
    "unique_name = f\"s3InteractionEnv_{int(time.time())}\"\n",
    "interpreter_response = cp_client.create_code_interpreter(\n",
    "    name=unique_name,\n",
    "    description=\"Environment for S3 file operations\",\n",
    "    executionRoleArn=execution_role_arn,\n",
    "    networkConfiguration={\n",
    "        'networkMode': 'PUBLIC'\n",
    "    }\n",
    ")\n",
    "interpreter_id = interpreter_response[\"codeInterpreterId\"]\n",
    "print(f\"Created interpreter: {interpreter_id}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. Starting a Session\n",
    "\n",
    "Create a session within the code interpreter to execute code."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:57:00.097783Z",
     "start_time": "2025-07-13T12:56:57.832645Z"
    }
   },
   "outputs": [],
   "source": [
    "# Start session\n",
    "session_response = dp_client.start_code_interpreter_session(\n",
    "    codeInterpreterIdentifier=interpreter_id,\n",
    "    name=\"s3InteractionSession\",\n",
    "    sessionTimeoutSeconds=900\n",
    ")\n",
    "session_id = session_response[\"sessionId\"]\n",
    "print(f\"Created session: {session_id}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 7. Helper Function for Tool Execution\n",
    "\n",
    "Define a utility function to simplify code interpreter tool invocation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:57:02.281362Z",
     "start_time": "2025-07-13T12:57:02.277560Z"
    }
   },
   "outputs": [],
   "source": [
    "def call_tool(tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:\n",
    "    response = dp_client.invoke_code_interpreter(\n",
    "        codeInterpreterIdentifier=interpreter_id,\n",
    "        sessionId=session_id,\n",
    "        name=tool_name,\n",
    "        arguments=arguments\n",
    "    )\n",
    "    for event in response[\"stream\"]:\n",
    "        return json.dumps(event[\"result\"], indent=2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8. Test Code Execution\n",
    "\n",
    "### 8.1 Test the code interpreter with a simple Hello World example."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:57:05.784367Z",
     "start_time": "2025-07-13T12:57:05.429150Z"
    }
   },
   "outputs": [],
   "source": [
    "# Test code execution\n",
    "# S3 Operations\n",
    "print(\"executing shell command \\n\")\n",
    "command_response = call_tool(\"executeCommand\",\n",
    "                              {\"command\": \"echo 'Hello World'\"})\n",
    "print(f\"command result: {command_response}\")\n",
    "\n",
    "# Parse and display results\n",
    "command_results = json.loads(command_response)\n",
    "print(command_results['structuredContent']['stdout'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.2 Next, lets install boto3 using PIP in to the sandbox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T12:58:00.949276Z",
     "start_time": "2025-07-13T12:57:59.563316Z"
    }
   },
   "outputs": [],
   "source": [
    "# Test code execution\n",
    "# S3 Operations\n",
    "print(\"executing shell command \\n\")\n",
    "command_response = call_tool(\"executeCommand\",\n",
    "                              {\"command\": \"pip install boto3\"})\n",
    "\n",
    "# Parse and display results\n",
    "command_results = json.loads(command_response)\n",
    "print(command_results['structuredContent']['stdout'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 9. File Operations and S3 Interaction by runninng commands\n",
    "\n",
    "#### 9.1 Write local file to sandbox"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T13:02:22.397060Z",
     "start_time": "2025-07-13T13:02:22.010485Z"
    }
   },
   "outputs": [],
   "source": [
    "# Write file to sandbox\n",
    "print(\"Writing file to sandbox\")\n",
    "try:\n",
    "    with open(local_file, 'r', encoding='utf-8') as local_file_content:\n",
    "        local_file_content = local_file_content.read()\n",
    "except FileNotFoundError:\n",
    "    print(f\"Error: The file '{local_file}' was not found.\")\n",
    "except Exception as e:\n",
    "    print(f\"An error occurred: {e}\")\n",
    "\n",
    "files_to_create = [{\n",
    "        \"path\": \"stats.py\",\n",
    "        \"text\": local_file_content\n",
    "}]\n",
    "write_files_response = call_tool(\"writeFiles\", {\"content\": files_to_create})\n",
    "print(f\"write files result: {write_files_response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 9.2 Create a S3 Bucket via code interpreter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T13:00:44.731145Z",
     "start_time": "2025-07-13T13:00:42.661104Z"
    }
   },
   "outputs": [],
   "source": [
    "# S3 Operations\n",
    "print(\"\\nCreating S3 bucket\")\n",
    "create_s3_response = call_tool(\"executeCommand\",\n",
    "                              {\"command\": f\"aws s3 mb {s3_path} --region {region}\"})\n",
    "print(f\"create result: {create_s3_response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 9.3 Upload file from code interpreter by running command to the S3 Bucket(created above)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T13:02:31.834784Z",
     "start_time": "2025-07-13T13:02:30.724996Z"
    }
   },
   "outputs": [],
   "source": [
    "print(\"\\nUploading file to S3\")\n",
    "upload_to_s3_response = call_tool(\"executeCommand\",\n",
    "                                 {\"command\": f\"aws s3 cp {files_to_create[0]['path']} {s3_path}\"})\n",
    "print(f\"upload result: {upload_to_s3_response}\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 9.4 List files from the S3 bucket by running a command in the code interpreter"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T13:02:35.644224Z",
     "start_time": "2025-07-13T13:02:34.539568Z"
    }
   },
   "outputs": [],
   "source": [
    "print(\"\\nListing files in S3\")\n",
    "list_s3_response = call_tool(\"executeCommand\",\n",
    "                            {\"command\": f\"aws s3 ls {s3_path}\"})\n",
    "print(f\"list result: {list_s3_response}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10. Cleanup\n",
    "\n",
    "Clean up resources by stopping the session and deleting the interpreter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-07-13T13:04:38.694932Z",
     "start_time": "2025-07-13T13:04:31.545319Z"
    }
   },
   "outputs": [],
   "source": [
    "# Cleanup\n",
    "print(\"Cleaning up session and interpreter\")\n",
    "dp_client.stop_code_interpreter_session(\n",
    "    codeInterpreterIdentifier=interpreter_id,\n",
    "    sessionId=session_id\n",
    ")\n",
    "print(\"Session stopped successfully\")\n",
    "\n",
    "cp_client.delete_code_interpreter(codeInterpreterId=interpreter_id)\n",
    "print(\"Interpreter deleted successfully\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
